﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics.OpenGL4;

namespace Common {
    public class Font2D:GlDisposableObjectBase {
        //int text2dTextureId;
        Texture2D texture;
        //int text2dVexturexBufferId;
        //int text2dUvBufferId;
        Vbo<Vector2> vertexBuffer, uvBuffer;
        //static int text2dShaderId;
         Shader shader;
         //int text2dUniformId;
        VertexAttribManager attribs = new VertexAttribManager();
        string textureUniformName;
        public static void GlBufferData<T>(BufferTarget target, T[] bufferData, BufferUsageHint usage) where T : struct {
            GL.BufferData(target, (IntPtr)(bufferData.Length * Marshal.SizeOf(default(T))), bufferData, usage);
        }
        public Font2D(string path, Shader shader, string textureUniformName) {
            initText2D(path, shader, textureUniformName);
        }
        public  void initText2D(string texturePath,Shader shader,string textureUniformName) {
            //text2dTextureId = DdsReader.LoadDds(texturePath);
            this.textureUniformName = textureUniformName;
            texture=Texture2D.Load(texturePath);
            //text2dVexturexBufferId = GL.GenBuffer();
            //text2dUvBufferId = GL.GenBuffer();
            vertexBuffer = new Vbo<Vector2>(new Vector2[0]);
            uvBuffer = new Vbo<Vector2>(new Vector2[0]);
            //text2dShaderId = Utility.LoadShader(File.ReadAllText("TextVertexShader.vertexshader"), File.ReadAllText("TextVertexShader.fragmentshader"));
            this.shader = shader;
            //text2dUniformId = GL.GetUniformLocation(shader.ID, "myTextureSampler");
            attribs.AddAttrib(2, vertexBuffer);
            attribs.AddAttrib(2, uvBuffer);
        }

        public  void printText2d(string text, int x, int y, int size) {
            int length = text.Length;
            List<Vector2> vertices = new List<Vector2>();
            List<Vector2> uvs = new List<Vector2>();
            CreateSquareData(text, x, y, size, length, vertices, uvs);
            //GL.BindBuffer(BufferTarget.ArrayBuffer, text2dVexturexBufferId);
            //GlBufferData<Vector2>(BufferTarget.ArrayBuffer, vertices.ToArray(), BufferUsageHint.StaticDraw);
            //GL.BindBuffer(BufferTarget.ArrayBuffer, text2dUvBufferId);
            //GlBufferData<Vector2>(BufferTarget.ArrayBuffer, uvs.ToArray(), BufferUsageHint.StaticDraw);
            vertexBuffer.SetBufferData(vertices.ToArray());
            uvBuffer.SetBufferData(uvs.ToArray());
            //GL.UseProgram(shader.ID);
            shader.Use();
            //GL.ActiveTexture(TextureUnit.Texture0);
            //GL.BindTexture(TextureTarget.Texture2D, texture.TextureId);
            //GL.Uniform1(text2dUniformId, 0);
            texture.Active(TextureUnit.Texture0, shader, textureUniformName);

            //GL.EnableVertexAttribArray(0);
            ////GL.BindBuffer(BufferTarget.ArrayBuffer, text2dVexturexBufferId);
            //GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer.Id);
            //GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 0, 0);

            //GL.EnableVertexAttribArray(1);
            ////GL.BindBuffer(BufferTarget.ArrayBuffer, text2dUvBufferId);
            //GL.BindBuffer(BufferTarget.ArrayBuffer, uvBuffer.Id);
            //GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 0, 0);
            attribs.Enable();

            GL.Enable(EnableCap.Blend);
            //GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
            GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);

            GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Count);
            GL.Disable(EnableCap.Blend);

            attribs.Disable();
            //GL.DisableVertexAttribArray(0);
            //GL.DisableVertexAttribArray(1);



        }

        private static void CreateSquareData(string text, int x, int y, int size, int length, List<Vector2> vertices, List<Vector2> uvs) {
            for (int i = 0; i < length; i++) {
                Vector2 vertexUpLeft = new Vector2(x + i * size, y + size);
                Vector2 vertexUpRight = new Vector2(x + i * size + size, y + size);
                Vector2 vertexDownRight = new Vector2(x + i * size + size, y);
                Vector2 vertexDownLeft = new Vector2(x + i * size, y);
                vertices.Add(vertexUpLeft);
                vertices.Add(vertexDownLeft);
                vertices.Add(vertexUpRight);

                vertices.Add(vertexDownRight);
                vertices.Add(vertexUpRight);
                vertices.Add(vertexDownLeft);

                char character = text[i];
                float uvX = (character % 16) / 16.0f;
                float uvY = (character / 16) / 16.0f;

                Vector2 uvUpLeft = new Vector2(uvX, uvY);
                Vector2 uvUpRight = new Vector2(uvX + 1.0f / 16.0f, uvY);
                Vector2 uvDownRight = new Vector2(uvX + 1.0f / 16.0f, uvY + 1.0f / 16.0f);
                Vector2 uvDownLeft = new Vector2(uvX, uvY + 1.0f / 16.0f);

                uvs.Add(uvUpLeft);
                uvs.Add(uvDownLeft);
                uvs.Add(uvUpRight);

                uvs.Add(uvDownRight);
                uvs.Add(uvUpRight);
                uvs.Add(uvDownLeft);
            }
        }

        protected override void OnDispose() {
            GlDisposableObjectBase.DisposeObjects(vertexBuffer,uvBuffer,texture);
        }
    }
}
